package com.share.device.service.impl;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.share.common.core.exception.ServiceException;
import com.share.device.service.IMapService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings({"unchecked", "rawtypes"})
public class MapServiceImpl implements IMapService {

    private final RestTemplate restTemplate;

    @Value("${tencent.map.key}")
    private String key;

    /**
     * 根据经纬度计算详细地址
     */
    @Override
    public JSONObject calculateLatLng(String keyword) {
        log.info("开始地理编码查询，关键词: {}", keyword);

        // 构建请求URL和参数
        String url = "https://apis.map.qq.com/ws/geocoder/v1/?address={address}&key={key}";
        Map<String, String> params = new HashMap<>();
        params.put("address", keyword);
        params.put("key", key);

        try {
            // 发送请求并获取响应
            JSONObject response = restTemplate.getForObject(url, JSONObject.class, params);
            log.debug("腾讯地图API响应: {}", response);

            // 检查API返回状态
            if (response == null) {
                log.error("地理编码查询失败，无响应数据");
                throw new ServiceException("地图解析异常，无响应数据");
            }

            int status = response.getIntValue("status");
            if (status != 0) {
                log.error("地理编码查询失败，状态码: {}}", status);
                throw new ServiceException("地图解析异常，错误码: " + status);
            }

            // 提取位置信息
            JSONObject result = response.getJSONObject("result");
            if (result == null) {
                log.error("地理编码查询结果格式异常，缺少'result'字段");
                throw new ServiceException("地图解析结果格式异常");
            }

            JSONObject location = result.getJSONObject("location");
            if (location == null) {
                log.error("地理编码查询结果格式异常，缺少'location'字段");
                throw new ServiceException("地图解析结果格式异常");
            }

            log.info("地理编码查询成功，经纬度: {}, {}", location.getDoubleValue("lng"), location.getDoubleValue("lat"));

            return location;
        } catch (HttpStatusCodeException e) {
            log.error("地理编码查询失败，HTTP状态码: {}, 响应体: {}", e.getStatusCode(), e.getResponseBodyAsString(), e);
            throw new ServiceException("地图API请求失败，HTTP状态码: " + e.getStatusCode());
        } catch (Exception e) {
            log.error("地理编码查询发生未知异常", e);
            throw new ServiceException("地图解析过程发生异常");
        }

    }

    /**
     * 调用腾讯地图API计算两点之间的步行距离
     *
     * @param startLongitude 起点经度
     * @param startLatitude  起点纬度
     * @param endLongitude   终点经度
     * @param endLatitude    终点纬度
     * @return 两点之间的步行距离，单位为米
     * @throws IllegalArgumentException 如果任何坐标参数为null
     * @throws ServiceException         如果调用地图服务失败或解析结果异常
     */
    @Override
    public Double calculateDistance(String startLongitude, String startLatitude, String endLongitude, String endLatitude) {
        // 记录方法调用，包含输入参数信息
        log.info("开始计算距离，起点坐标: {}:{}，终点坐标: {}:{}", startLongitude, startLatitude, endLongitude, endLatitude);

        // 参数校验，确保所有坐标参数都不为null
        if (startLongitude == null || startLatitude == null || endLongitude == null || endLatitude == null) {
            log.error("坐标参数存在null值");
            throw new ServiceException("坐标参数不能为空");
        }

        // 构造地图API请求URL，使用占位符方式便于参数替换
        String url = "https://apis.map.qq.com/ws/direction/v1/walking/?from={from}&to={to}&key={key}";

        // 准备请求参数，注意坐标格式为"纬度,经度"
        Map<String, String> map = new HashMap<>();
        map.put("from", startLatitude + "," + startLongitude);
        map.put("to", endLatitude + "," + endLongitude);
        map.put("key", key);

        try {
            // 发送HTTP请求并获取JSON响应
            JSONObject result = restTemplate.getForObject(url, JSONObject.class, map);

            // 检查API响应状态，状态码0表示成功
            if (result == null || result.getIntValue("status") != 0) {
                String errorMsg = result != null ? "地图服务调用失败，状态码: " + result.getIntValue("status") : "地图服务无响应";
                log.error(errorMsg);
                throw new ServiceException("地图服务调用失败");
            }
            // 解析响应数据，提取第一条路线的距离信息
            return result.getJSONObject("result").getJSONArray("routes").getJSONObject(0).getBigDecimal("distance").doubleValue();
        } catch (HttpStatusCodeException e) {
            // 处理HTTP请求异常，如404、500等状态码
            log.error("HTTP请求异常，状态码: {}", e.getStatusCode(), e);
            throw new ServiceException("地图服务连接失败");
        } catch (JSONException | NullPointerException e) {
            // 处理JSON解析异常或空指针异常
            log.error("解析地图响应失败", e);
            throw new ServiceException("地图服务响应格式异常");
        } catch (Exception e) {
            // 捕获其他未知异常
            log.error("计算距离时发生未知异常", e);
            throw new ServiceException("距离计算失败");
        }
    }
}
